package com.swingson.properties.specificclass_impl;

import com.swingson.Swingson;
import com.swingson.SwingsonGui;
import com.swingson.jsonparser.JsonElement;
import com.swingson.other.ConditionAndAction;
import com.swingson.other.MethodExecutor;
import com.swingson.properties.AbstractAssignMethodPropertyProcessor;
import com.swingson.properties.specificclass_impl.OnChangeComboBoxPropertyProcessor.ChangeType;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JComponent;

/**
 * @author sad
 */
public class OnChangeComboBoxPropertyProcessor extends AbstractAssignMethodPropertyProcessor {

    public enum ChangeType {

        SELECT, DESELECT
    };
    private final ChangeType changeType;

    static List<Class[]> argumentsVariants = new ArrayList<Class[]>() {
        {
            add(new Class[]{});//no parameters
            add(new Class[]{ItemEvent.class});
            add(new Class[]{Object.class});//affected item
        }
    };

    public OnChangeComboBoxPropertyProcessor(ChangeType changeType) {
        this.changeType = changeType;
    }

    @Override
    protected String getName() {
        return "On Change Event Listener";
    }

    @Override
    protected List<Class[]> methodArgumentsVariants() {
        return argumentsVariants;
    }

    @Override
    protected void attachMethod(JsonElement jsonElement, final JComponent component, final SwingsonGui gui, String propertyName, final MethodExecutor mExecutor, final int methodArgumentVariant, final ConditionAndAction conditionAndAction) {
        EventExecutor<ItemEvent> executor = new EventExecutor<ItemEvent>() {
            @Override
            public void execute(ItemEvent event) {
                if (!Swingson.isEnabledUserInput()) {
                    return;
                }
                try {
                    switch (methodArgumentVariant) {
                        case 0:
                            mExecutor.invoke();
                            break;
                        case 1:
                            mExecutor.invoke(event);
                            break;
                        case 2:
                            mExecutor.invoke(event.getItem());
                            break;
                    }

                    runAction(conditionAndAction, gui, component);
                } catch (Throwable ex) {
                    onError(gui, ex);
                }
            }
        };

        ItemListenerWrapper listener = new ItemListenerWrapper();
        listener.setOnChange(executor);
        ((JComboBox) component).addItemListener(listener);

    }

    private class ItemListenerWrapper implements ItemListener {

        private EventExecutor onChange;

        public void setOnChange(EventExecutor onChange) {
            this.onChange = onChange;
        }

        @Override
        public void itemStateChanged(ItemEvent e) {
            if (((changeType == ChangeType.SELECT) && (e.getStateChange() == ItemEvent.SELECTED))
                    || ((changeType == ChangeType.DESELECT) && (e.getStateChange() == ItemEvent.DESELECTED))) {
                if (onChange != null) {
                    onChange.execute(e);
                }
            }
        }
    }
}
